using System;
using System.Collections.Generic;
using System.Text;
using Mud.Common.Messages;
using System.Threading;

namespace Mud.Common.Threading
{
    /// <summary>
    /// A list which uses a WaitHandle to signal when it is not empty.
    /// </summary>
    /// <typeparam name="T">Any value.</typeparam>
    public class WaitableList<T> : IList<T>
    {

        private List<T> _impl = new List<T>();

        /// <summary>
        /// Object can wait on this WaitHandle for new items in the list.
        /// </summary>
        public WaitHandle WaitForItem
        {
			get { return _waitForItem; }
        }
		private ManualResetEvent _waitForItem = new ManualResetEvent(false);

		/// <summary>
		/// This property can be checked if there are items in the list without locking the list.
		/// </summary>
		public int ItemExists {
			get { return _itemExists; }
		}
		private int _itemExists;


        private void CheckItemExists()
        {
			if (_impl.Count == 0) {
				if (_itemExists > 0)
					Interlocked.Decrement(ref _itemExists);
				this._waitForItem.Reset();
			} else {
				if (_itemExists == 0)
					Interlocked.Increment(ref _itemExists);
				this._waitForItem.Set();
			}
        }

        public void AddRange(IEnumerable<T> items)
        {
            foreach (T item in items)
                this.Add(item);
        }

        #region IList<T> Members

        public int IndexOf(T item)
        {
            return _impl.IndexOf(item);
        }

        public void Insert(int index, T item)
        {
            _impl.Insert(index, item);
            CheckItemExists();
        }

        public void RemoveAt(int index)
        {
            _impl.RemoveAt(index);
            CheckItemExists();
        }

        public T this[int index]
        {
            get
            {
                return _impl[index];
            }
            set
            {
                _impl[index] = value;
            }
        }

        #endregion

        #region ICollection<T> Members

        public void Add(T item)
        {
            _impl.Add(item);
            CheckItemExists();
        }

        public void Clear()
        {
            _impl.Clear();
            CheckItemExists();
        }

        public bool Contains(T item)
        {
            return _impl.Contains(item);
        }

        public void CopyTo(T[] array, int arrayIndex)
        {
            _impl.CopyTo(array, arrayIndex);
        }

        public int Count
        {
            get { return _impl.Count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool Remove(T item)
        {
            bool result =_impl.Remove(item);
            CheckItemExists();
            return result;
        }

        #endregion

        #region IEnumerable<T> Members

        public IEnumerator<T> GetEnumerator()
        {
            return _impl.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return ((System.Collections.IEnumerable)_impl).GetEnumerator();
        }

        #endregion
    }
}
